﻿using Microsoft.SqlServer.Server;
using SketchUpAPI.NET.Enums;
using SketchUpAPI.NET.SketchUp.Exception;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;

namespace SketchUpAPI.NET.Objects
{
    /// <summary>
    /// 尺寸格式化器，用于将长度、面积、体积转换成字符串，或从字符串转换为值
    /// </summary>
    /// <remarks>对 SketchUpAPI 中的 SULengthFormatterRef 的包装</remarks>
    public class LengthFormatter : ObjectBase
    {
        #region API 函数
        /// <summary>
        /// 创建一个单位设置类
        /// </summary>
        /// <param name="formatter"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SULengthFormatterCreate(out IntPtr formatter);

        /// <summary>
        /// 释放设置类
        /// </summary>
        /// <param name="formatter"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SULengthFormatterRelease(ref IntPtr formatter);

        /// <summary>
        /// 获取长度精度
        /// </summary>
        /// <param name="formatter"></param>
        /// <param name="precision"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SULengthFormatterGetPrecision(IntPtr formatter, out int precision);

        /// <summary>
        /// 设置长度精度
        /// </summary>
        /// <param name="formatter"></param>
        /// <param name="precision"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SULengthFormatterSetPrecision(IntPtr formatter, int precision);

        /// <summary>
        /// 获取面积精度
        /// </summary>
        /// <param name="formatter"></param>
        /// <param name="precision"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SULengthFormatterGetAreaPrecision(IntPtr formatter, out int precision);

        /// <summary>
        /// 设置面积精度
        /// </summary>
        /// <param name="formatter"></param>
        /// <param name="precision"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SULengthFormatterSetAreaPrecision(IntPtr formatter, int precision);

        /// <summary>
        /// 获取体积精度
        /// </summary>
        /// <param name="formatter"></param>
        /// <param name="precision"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SULengthFormatterGetVolumePrecision(IntPtr formatter, out int precision);

        /// <summary>
        /// 设置体积精度
        /// </summary>
        /// <param name="formatter"></param>
        /// <param name="precision"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SULengthFormatterSetVolumePrecision(IntPtr formatter, int precision);

        /// <summary>
        /// 获取格式类型
        /// </summary>
        /// <param name="formatter"></param>
        /// <param name="format"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SULengthFormatterGetFormat(IntPtr formatter, out LengthFormatType format);

        /// <summary>
        /// 设置格式类型
        /// </summary>
        /// <param name="formatter"></param>
        /// <param name="format"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SULengthFormatterSetFormat(IntPtr formatter, LengthFormatType format);

        /// <summary>
        /// 获取长度单位
        /// </summary>
        /// <param name="formatter"></param>
        /// <param name="units"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SULengthFormatterGetUnits(IntPtr formatter, out UnitLengthType units);

        /// <summary>
        /// 设置长度单位
        /// </summary>
        /// <param name="formatter"></param>
        /// <param name="units">单位</param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SULengthFormatterSetUnits(IntPtr formatter, UnitLengthType units);

        /// <summary>
        /// 设置面积单位
        /// </summary>
        /// <param name="formatter"></param>
        /// <param name="units"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SULengthFormatterSetAreaUnits(IntPtr formatter, UnitAreaType units);

        /// <summary>
        /// 获取面积单位
        /// </summary>
        /// <param name="formatter"></param>
        /// <param name="units"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SULengthFormatterGetAreaUnits(IntPtr formatter, out UnitAreaType units);

        /// <summary>
        /// 设置体积单位
        /// </summary>
        /// <param name="formatter"></param>
        /// <param name="units"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SULengthFormatterSetVolumeUnits(IntPtr formatter, UnitVolumeType units);

        /// <summary>
        /// 获取体积单位
        /// </summary>
        /// <param name="formatter"></param>
        /// <param name="units"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SULengthFormatterGetVolumeUnits(IntPtr formatter, out UnitVolumeType units);

        /// <summary>
        /// 获取是否显示单位格式
        /// </summary>
        /// <param name="formatter"></param>
        /// <param name="suppress"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SULengthFormatterGetSuppressUnits(IntPtr formatter, out bool suppress);

        /// <summary>
        /// 设置是否显示单位格式
        /// </summary>
        /// <param name="formatter"></param>
        /// <param name="suppress"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SULengthFormatterSetSuppressUnits(IntPtr formatter, bool suppress);

        /// <summary>
        /// 格式化长度
        /// </summary>
        /// <param name="formatter"></param>
        /// <param name="length"></param>
        /// <param name="strip">是否去掉末尾的0和小数点</param>
        /// <param name="txt"><see cref="StringRef"/></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SULengthFormatterGetLengthString(IntPtr formatter, double length, bool strip, ref IntPtr txt);

        /// <summary>
        /// 格式化面积
        /// </summary>
        /// <param name="formatter"></param>
        /// <param name="area"></param>
        /// <param name="txt"><see cref="StringRef"/></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SULengthFormatterGetAreaString(IntPtr formatter, double area, ref IntPtr txt);

        /// <summary>
        /// 格式化体积
        /// </summary>
        /// <param name="formatter"></param>
        /// <param name="volume"></param>
        /// <param name="txt"><see cref="StringRef"/></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SULengthFormatterGetVolumeString(IntPtr formatter, double volume, ref IntPtr txt);

        /// <summary>
        /// 读取数据
        /// </summary>
        /// <param name="formatter"></param>
        /// <param name="txt"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SULengthFormatterParseString(IntPtr formatter, IntPtr txt, out double value);

        /// <summary>
        /// 单位是建筑时，是否强制显示0
        /// </summary>
        /// <param name="formatter"></param>
        /// <param name="force_inch"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SULengthFormatterSetForceInchDisplay(IntPtr formatter, bool force_inch);

        /// <summary>
        /// 单位是建筑时，是否强制显示0
        /// </summary>
        /// <param name="formatter"></param>
        /// <param name="force_inch"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SULengthFormatterGetForceInchDisplay(IntPtr formatter, out bool force_inch);
        #endregion

        /// <summary>
        /// 显示单位
        /// </summary>
        public bool SuppressUnits
        {
            get
            {
                SketchUpExceptionHelper.ThrowSUResult(SULengthFormatterGetSuppressUnits(Id, out bool s));
                return s;
            }
            set
            {
                SketchUpExceptionHelper.ThrowSUResult(SULengthFormatterSetSuppressUnits(Id, value));
            }
        }

        /// <summary>
        /// 单位是建筑英寸时，是否强制显示0
        /// </summary>
        public bool ShowZero
        {
            get
            {
                SketchUpExceptionHelper.ThrowSUResult(SULengthFormatterGetForceInchDisplay(Id, out bool s));
                return s;
            }
            set
            {
                SketchUpExceptionHelper.ThrowSUResult(SULengthFormatterSetForceInchDisplay(Id, value));
            }
        }

        /// <summary>
        /// 设置格式
        /// </summary>
        /// <remarks>如：建筑、十进制、小数、工程</remarks>
        public LengthFormatType LengthFormat
        {
            get
            {
                SketchUpExceptionHelper.ThrowSUResult(SULengthFormatterGetFormat(Id, out LengthFormatType format));
                return format;
            }
            set
            {
                SketchUpExceptionHelper.ThrowSUResult(SULengthFormatterSetFormat(Id, value));
            }
        }

        /// <summary>
        /// 长度单位
        /// </summary>
        public UnitLengthType LengthUnit
        {
            get
            {
                SketchUpExceptionHelper.ThrowSUResult(SULengthFormatterGetUnits(Id, out UnitLengthType units));
                return units;
            }
            set
            {
                SketchUpExceptionHelper.ThrowSUResult(SULengthFormatterSetUnits(Id, value));
            }
        }

        /// <summary>
        /// 长度精度
        /// </summary>
        public int LengthPrecision
        {
            get
            {
                SketchUpExceptionHelper.ThrowSUResult(SULengthFormatterGetPrecision(Id, out int precision));
                return precision;
            }
            set
            {
                SketchUpExceptionHelper.ThrowSUResult(SULengthFormatterSetPrecision(Id, value));
            }
        }

        /// <summary>
        /// 面积单位
        /// </summary>
        public UnitAreaType AreaUnit
        {
            get
            {
                SketchUpExceptionHelper.ThrowSUResult(SULengthFormatterGetAreaUnits(Id, out UnitAreaType u));
                return u;
            }
            set
            {
                SketchUpExceptionHelper.ThrowSUResult(SULengthFormatterSetAreaUnits(Id, value));
            }
        }

        /// <summary>
        /// 面积精度
        /// </summary>
        public int AreaPrecision
        {
            get
            {
                SketchUpExceptionHelper.ThrowSUResult(SULengthFormatterGetAreaPrecision(Id, out int p));
                return p;
            }
            set
            {
                SketchUpExceptionHelper.ThrowSUResult(SULengthFormatterSetAreaPrecision(Id, value));
            }
        }

        /// <summary>
        /// 体积单位
        /// </summary>
        public UnitVolumeType VolumeUnit
        {
            get
            {
                SketchUpExceptionHelper.ThrowSUResult(SULengthFormatterGetVolumeUnits(Id, out UnitVolumeType u));
                return u;
            }
            set
            {
                SketchUpExceptionHelper.ThrowSUResult(SULengthFormatterSetVolumeUnits(Id, value));
            }
        }

        /// <summary>
        /// 体积精度
        /// </summary>
        public int VolumePrecision
        {
            get
            {
                SketchUpExceptionHelper.ThrowSUResult(SULengthFormatterGetVolumePrecision(Id, out int p));
                return p;
            }
            set
            {
                SketchUpExceptionHelper.ThrowSUResult(SULengthFormatterSetVolumePrecision(Id, value));
            }
        }

        public LengthFormatter()
        {
            SketchUpExceptionHelper.ThrowSUResult(SULengthFormatterCreate(out Id));
        }

        internal LengthFormatter(IntPtr id) => Id = id;

        /// <summary>
        /// 获取格式化长度字符串
        /// </summary>
        /// <param name="length"></param>
        /// <param name="strip">是否去掉末尾的0</param>
        /// <returns></returns>
        public string FormatLength(double length, bool strip)
        {
            StringRef s = StringRef.Empty;
            SketchUpExceptionHelper.ThrowSUResult(SULengthFormatterGetLengthString(Id, length, strip, ref s.Id));
            return s.Dispose();
        }

        /// <summary>
        /// 获取面积字符串
        /// </summary>
        /// <param name="area"></param>
        /// <returns></returns>
        public string FormatArea(double area)
        {
            StringRef s = StringRef.Empty;
            SketchUpExceptionHelper.ThrowSUResult(SULengthFormatterGetAreaString(Id, area, ref s.Id));
            return s.Dispose();
        }

        /// <summary>
        /// 获取体积字符串
        /// </summary>
        /// <param name="volume"></param>
        /// <returns></returns>
        public string FormatVolume(double volume)
        {
            StringRef s = StringRef.Empty;
            SketchUpExceptionHelper.ThrowSUResult(SULengthFormatterGetVolumeString(Id, volume, ref s.Id));
            return s.Dispose();
        }

        /// <summary>
        /// 从字符串获取值
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public double Parse(string str)
        {
            StringRef s = new StringRef(str);
            SketchUpExceptionHelper.ThrowSUResult(SULengthFormatterParseString(Id, s.Id, out double value));
            s.Dispose();
            return value;
        }

        /// <summary>
        /// 尝试从字符串转换值
        /// </summary>
        /// <param name="str"></param>
        /// <param name="value"></param>
        /// <returns>是否转换成功</returns>
        public bool TryParse(string str, out double value)
        {
            StringRef s = new StringRef(str);
            var result = SULengthFormatterParseString(Id, s.Id, out value);
            s.Dispose();

            if (result == SUResult.SU_ERROR_NONE)
            {
                return true;
            }
            else
            {
                value = 0;
                return false;
            }
        }

        public override void Dispose()
        {
            SketchUpExceptionHelper.ThrowSUResult(SULengthFormatterRelease(ref Id));
        }
    }
}